fix: unbreak scheduled PR pipeline (silent gh-pr-create denials since June 14)#1047
fix: unbreak scheduled PR pipeline (silent gh-pr-create denials since June 14)#1047lroolle wants to merge 2 commits into
Conversation
Since ~June 14 every scheduled run pushed a docs branch, failed silently on 'gh pr create', barked a notification, and exited green: claude-code-action@main changed claude_args parsing so 'Bash(gh pr:*)' split on the space into two invalid permission rules. Result: 31 orphan branches, zero PRs, three weeks of stale main. - Move tool permissions to .claude/settings.json (JSON survives any arg parsing; settingSources=project already loads it in CI) - Pin claude-code-action to v1.0.168 instead of the moving @main - Add a Verify outcome tripwire: pushed branch without a PR, or uncommitted changes after the agent step, now fail the run - Bark protocol: notify only after a real PR URL exists; bark a failure alert otherwise - fetcher: record failures in .metadata.json (they were discarded), print per-host failure breakdown, support JINA_API_KEY (r.jina.ai rate limiting caused 574 of 731 failures), skip terraform pages that serve no .md variant (the other 157) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: df50edb8be
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| run: | | ||
| BRANCH=$(git branch --show-current) | ||
| if [ -n "$(git status --porcelain)" ]; then |
There was a problem hiding this comment.
Don't fail intentionally ignored low-signal diffs
This dirty-workspace tripwire conflicts with the prompt above that still tells the agent to “do nothing, exit 0” when the fetch produces only low-signal changes such as blog/research, GitHub mirror content, or .metadata.json. In those scheduled runs the fetcher has already modified the worktree, so an agent that correctly decides no commit/PR is warranted leaves changes behind and this verification step turns the run red even though nothing silently failed. Either have the agent reset ignored changes before exiting or exempt the explicitly ignored paths here.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR restores reliability and observability of the scheduled “Fetch Claude Code Docs” pipeline after PR creation was silently denied (while runs still reported success), by pinning the Claude Code action, moving tool permissions into project settings, and adding a post-run tripwire plus better fetch failure reporting.
Changes:
- Pin
anthropics/claude-code-actionto a fixed version and move tool permissions to.claude/settings.jsonto avoid workflow-arg parsing regressions. - Add a “Verify outcome” step and tighten notification guidance so the workflow fails loudly when no PR is created or the workspace is left dirty.
- Improve the fetcher with Jina API key support, terraform page skipping, and failure recording/printing.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| scripts/fetcher.py | Adds optional Jina auth headers, skips terraform pages, and records/prints failures for better visibility into fetch issues. |
| .gitignore | Stops ignoring root .claude/ wholesale while keeping only .claude/settings.json tracked. |
| .github/workflows/fetch-claude-docs.yml | Pins the action, wires JINA_API_KEY, updates notification protocol, and adds a post-agent tripwire to fail on silent PR creation failures. |
| .claude/settings.json | Defines tool permissions in project settings to avoid fragile CLI arg parsing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| content = await self.fetch_bytes( | ||
| session, f"https://r.jina.ai/{url}", headers=self._jina_headers()) |
| content = await self.fetch_bytes( | ||
| session, f"https://r.jina.ai/{url}", headers=self._jina_headers()) |
| by_host = defaultdict(int) | ||
| for r in failed: | ||
| by_host[r["url"].split("/")[2]] += 1 | ||
| print("\nFailed by host:") |
| "failures": [ | ||
| {"url": r["url"], "error": str(r.get("error", ""))[:200]} | ||
| for r in results if r.get("status") == "failed" | ||
| ], |
support.claude.com now serves a .md variant for every article (verified 2026-07-08: 200 text/markdown on all sitemap URLs), so support articles fetch directly like platform/code/mcp docs - no proxy, no rate limits, 355/355 instead of 4/355 through jina. anthropic.com blog (engineering/research/news/product) remains HTML-only (no llms.txt, no .md, no content negotiation), and the jina path had been ~95% dead from rate limiting anyway. Freeze it: content/blog/ stays as a static archive, sources disabled in sources.json with dated notes, --section choices trimmed. Full run after: 3231/3231 downloaded, 0 failed (was 2907/3638, 731 failed). Also removes the JINA_API_KEY workflow plumbing added earlier on this branch - no secret needed anymore. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The incident
Every scheduled run since ~June 14: fetch works → Claude commits and pushes a branch →
gh pr createsilently denied → Bark notification sent anyway → run exits green. 31 orphandocs/claude-code-v2.1.*branches, zero PRs, main stale for 3 weeks, and daily false-positive notifications.Root cause: the workflow tracked
anthropics/claude-code-action@main, whoseclaude_argsparsing changed to split--allowedTools Bash(gh pr:*),…on whitespace — producingBash(gh+pr:*), two invalid rules.Bash(git:*)survived (no space), which is why branches kept getting pushed while PR creation died.The fix (defense in depth)
.claude/settings.json— JSON is immune to arg-parsing changes; CI already loads project settingsv1.0.168instead of moving@mainVerify outcomestep: pushed branch without PR, or dirty workspace after agent step → red run.metadata.json+ per-host breakdown printed (731/run were silently discarded)Jina.ai deprecated (second commit)
The 731 failures broke down as: 574 = r.jina.ai rate limiting (blog + support proxied fetches), 157 = platform terraform pages with no
.mdvariant. Resolution — remove the jina dependency entirely:.mdvariant directly (verified 2026-07-08) → fetched like platform/code/mcp docs. 355/355 articles vs 4/355 through rate-limited jina..md/ content negotiation) → frozen.content/blog/stays as a static archive; sources disabled insources.jsonwith dated notes;--sectionchoices trimmed..mdupstream).JINA_API_KEYsecret needed — that plumbing is removed.Verified
--section supportisolated run: 355/355.claude/settings.jsonload path confirmed against the action'ssettingSources: [user, project, local]Follow-ups (not in this PR)
content/github/**mirrors ship.claude/dirs the root ignore used to swallow — decide whether to archive them🤖 Generated with Claude Code